home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 October: Mac OS SDK / Dev.CD Oct 97 SDK1.toast / Development Kits (Disc 1) / Macintosh Drag and Drop / Demo Applications / DragsAndLists / DragSupport.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-04  |  7.1 KB  |  302 lines  |  [TEXT/MPS ]

  1. #if defined(UseDumpFiles)
  2.  
  3.     #include "DumpHeader.h"
  4.     
  5. #else
  6.  
  7.     #include <Drag.h>    
  8.     #include <Errors.h>
  9.     #include <GestaltEqu.h>
  10.  
  11. #endif
  12.  
  13. #include "ListCode.h"
  14. #include "DragSupport.h"
  15.  
  16. DragHandlerGlobals pDragGlobals;
  17.  
  18.  
  19.  
  20. /*-----------------------------------------------------------------*/
  21. Boolean DragMgrPresent(void)
  22. {
  23.     OSErr    err;
  24.     long    response = 0L;
  25.     
  26.     err = Gestalt(gestaltDragMgrAttr, &response);
  27.     
  28.     if ((err == noErr) 
  29.         && (response && (1 << gestaltDragMgrPresent) != 0))
  30.         return true;
  31.  
  32.     else
  33.         return false;                 
  34. }
  35.  
  36.  
  37. /*-----------------------------------------------------------------
  38.  
  39.    InstallDragHandlers attaches my tracking and receive handlers to
  40.    one of the application's windows
  41.  
  42. */
  43. OSErr InstallDragHandlers(WindowPtr theWindow)
  44. {    
  45.     OSErr     err;
  46.     
  47.     if (DragMgrPresent()) {
  48.         err = InstallTrackingHandler(DragTracker, theWindow, nil);
  49.     
  50.         if (err == noErr)  {
  51.             err = InstallReceiveHandler(DragReceiver, theWindow, nil);
  52.             
  53.             if (err != noErr)
  54.                 (void) RemoveTrackingHandler(DragTracker, theWindow);
  55.         }
  56.     }
  57.     if (err != noErr) Debugger();
  58.     
  59.     return err;
  60. }
  61.  
  62.  
  63. /*-----------------------------------------------------------------
  64.  
  65.    RemoveDragHandlers removes my tracking and receive handlers from
  66.    one of the application's windows (prior to the window's disposal,
  67.    presumably)
  68.  
  69. */
  70. void RemoveDragHandlers(WindowPtr theWindow)
  71. {
  72.     if (DragMgrPresent()) {
  73.         RemoveReceiveHandler(DragReceiver, theWindow);
  74.         RemoveTrackingHandler(DragTracker, theWindow);
  75.     }
  76. }
  77.  
  78.  
  79. /*-----------------------------------------------------------------
  80.  
  81.    DragItemsAreAcceptable returns true if the contents (data) of
  82.    the drag are and HFS flavor
  83.  
  84.    DragItemsAreAcceptable is called by the tracking and 
  85.    receive handlers
  86.  
  87. */
  88. Boolean DragItemsAreAcceptable(DragReference theDrag)
  89. {
  90.     OSErr            err;
  91.     unsigned short    totalItems;
  92.     ItemReference    itemRef;
  93.     Boolean            acceptIt;
  94.     OSType            currOSType;
  95.     Size            flavorDataSize;
  96.     
  97.     acceptIt = false;
  98.  
  99.     // this app can only accept the drag of a single item
  100.     err = CountDragItems(theDrag, &totalItems);
  101.  
  102.     if (err == noErr && totalItems == 1)  {
  103.         // get the reference number of the dragged item
  104.         err = GetDragItemReferenceNumber(theDrag, 1, &itemRef);
  105.  
  106.         if (err == noErr)  {
  107.             // check if the item is from the Finder
  108.             flavorDataSize = sizeof(OSType);
  109.             err = GetFlavorData(theDrag, itemRef, myPersonalFlavorType, &currOSType,
  110.                 &flavorDataSize, 0);
  111.             
  112.             if (err == noErr) 
  113.                 acceptIt = true;
  114.         }
  115.     }
  116.     return acceptIt;
  117. }
  118.  
  119.  
  120. /*-----------------------------------------------------------------
  121.  
  122.    DragIsNotInSourceWindow returns true if the drag in progress
  123.    is not in the same window it originated in
  124.    
  125.    DragIsNotInSourceWindow is called by the tracking and receive handlers
  126.    
  127.    Note that, if this application allowed items to be dragged within
  128.    its windows, this function would not be appropriate.
  129.    Instead, hilighting would probably occur in the source window
  130.    when the dragHasLeftSourceWindow flag is set, and the receive
  131.    handler wouldn't check this at all
  132.  
  133. */
  134. Boolean DragIsNotInSourceWindow(DragReference theDrag)
  135. {
  136.     DragAttributes currDragFlags;
  137.     
  138.     (void) GetDragAttributes(theDrag, &currDragFlags);
  139.     return ((currDragFlags & dragInsideSenderWindow) == 0);
  140. }
  141.  
  142.  
  143. /*-----------------------------------------------------------------
  144.  
  145.    DragTracker is called by the drag manager whenever a drag is
  146.    over one of the application's windows
  147.  
  148.    upon entry, the current port has been set to theWindow by the Drag Manager
  149.  
  150. */
  151. pascal OSErr DragTracker(DragTrackingMessage theMessage, WindowPtr theWindow,
  152.     void *handlerRefCon, DragReference theDrag)
  153. {
  154. #pragma unused (theWindow, handlerRefCon)
  155.  
  156.     RgnHandle    tempRgn;
  157.     Boolean        mouseInList;
  158.     OSErr        err;
  159.     
  160.     err = noErr;
  161.  
  162.     switch (theMessage) {
  163.     
  164.         case dragTrackingEnterHandler:
  165.             
  166.             //
  167.             // Any initialization for this window handler.
  168.             //
  169.             pDragGlobals.acceptableDragFlag = 
  170.                 DragItemsAreAcceptable(theDrag);
  171.             pDragGlobals.hilitedList = false;
  172.             
  173.             // let the drag manager know if we can't accept this drag
  174.             if (!pDragGlobals.acceptableDragFlag)
  175.                 err = dragNotAcceptedErr;
  176.             break;
  177.             
  178.         case dragTrackingEnterWindow: 
  179.         case dragTrackingInWindow:
  180.         case dragTrackingLeaveWindow:
  181.             
  182.             //
  183.             // Highlighting of the window during a drag is done
  184.             // here.  Do it only if we can accept these items
  185.             // and we're not in the source window...
  186.             //
  187.             
  188.             if (pDragGlobals.acceptableDragFlag) {
  189.                 //
  190.                 // Unless the mouse is leaving the visible area of the
  191.                 // window, check if it's in the window's content region
  192.                 //
  193.                 
  194.                 if (theMessage == dragTrackingLeaveWindow)
  195.                     mouseInList = false;
  196.  
  197.                 else {
  198.                     Point localPt;
  199.                 
  200.                     (void) GetDragMouse(theDrag, &localPt, 0L);
  201.                     GlobalToLocal(&localPt);
  202.                     mouseInList = PtInDestList(localPt);
  203.                 }
  204.  
  205.                 //
  206.                 // If the mouse is in the list
  207.                 //
  208.  
  209.                 if ((mouseInList == true)
  210.                     && (pDragGlobals.hilitedList == false)) {
  211.                     Rect    nuSpaceRect;
  212.  
  213.                     GetDestListRect(&nuSpaceRect);
  214.  
  215.                     tempRgn = NewRgn();
  216.                     RectRgn(tempRgn, &nuSpaceRect);
  217.  
  218.                     // draw the hilight
  219.                     if (ShowDragHilite(theDrag, tempRgn, true) == noErr)
  220.                         // remember where hilighting is on
  221.                         pDragGlobals.hilitedList = mouseInList;                    
  222.                     
  223.                     DisposeRgn(tempRgn);
  224.                 }
  225.                 
  226.                 //
  227.                 // else if the mouse is not in the content region
  228.                 // and the window is hilighted, erase the hilight
  229.                 //
  230.  
  231.                 else if ((mouseInList == false) 
  232.                             && (pDragGlobals.hilitedList == true))
  233.                     if (HideDragHilite(theDrag) == noErr)
  234.                         // remember that nothing is hilited
  235.                         pDragGlobals.hilitedList = false;
  236.  
  237.             }
  238.             break;
  239.  
  240.         // do nothing for the leaveHandler message
  241.         case dragTrackingLeaveHandler:
  242.             break;
  243.         
  244.         // let the drag manager know if we didn't recognize the message
  245.         default:
  246.             err = paramErr;
  247.     }
  248.     
  249.     return err;
  250. }
  251.  
  252.  
  253. /*-----------------------------------------------------------------
  254.  
  255.    DragReceiver is called by the drag manager whenever a drag is
  256.    ends on one of the application's windows
  257.  
  258. */
  259. pascal OSErr DragReceiver(WindowPtr theWindow, void *handlerRefCon, 
  260.         DragReference theDrag)
  261. {
  262. #pragma unused (theWindow, handlerRefCon)
  263.     ItemReference    itemRef;
  264.     Size            dataSize;
  265.     OSType            theOSType;
  266.     OSErr            err = noErr;
  267.     unsigned short    numItems, counter;
  268.  
  269.     if (!DragItemsAreAcceptable(theDrag) || (pDragGlobals.hilitedList == false))
  270.         return dragNotAcceptedErr;
  271.  
  272.     CountDragItems(theDrag, &numItems);
  273.     
  274.     for (counter = 1; counter <= numItems; counter++) {
  275.         err = GetDragItemReferenceNumber(theDrag, counter, &itemRef);
  276.         if (err != noErr)  goto BailOut;
  277.  
  278.         dataSize = sizeof(OSType);
  279.         err = GetFlavorData(theDrag, itemRef, myPersonalFlavorType, &theOSType, &dataSize, 0);
  280.  
  281.         //
  282.         // OK, we're going to first remove the drag hilite from here, because
  283.         // not doing so would result in a cleared out list rect, and when
  284.         // we go through the trackingLeaveWindow message up above, the
  285.         // HideDragHilite() call would draw the border again (since it's drawn
  286.         // in XOr mode).
  287.         //
  288.  
  289.         if (pDragGlobals.hilitedList == true) {
  290.             if (HideDragHilite(theDrag) == noErr)
  291.                 // remember that nothing is hilited
  292.                 pDragGlobals.hilitedList = false;
  293.         }
  294.         AddToDestList(theOSType);
  295.     }
  296.     
  297. BailOut:
  298.     return err;
  299. NoDragProcess:
  300.     return dragNotAcceptedErr;
  301. }
  302.